package com.fyl.basic_algorithm.hashtable;

/**
 * @author 冯永龙
 * @date 2021/3/31 9:28
 */
public class LRUBaseHashTable<K, V> {
    //默认链表容量
    private final static Integer DEFAULT_CAPACITY = 10;
    //头结点
    private DNode<K, V> headNode;
    //尾节点
    private DNode<K, V> tailNode;
    //链表长度
    private Integer length;
    //链表容量
    private Integer capacity;
    //散列表储存key
    private HashTable<K, DNode<K, V>> table;

    //双向链表
    static class DNode<K, V> {
        private K key;
        private V value;
        //前驱指针
        private DNode<K, V> prev;
        //后继指针
        private DNode<K, V> next;

        public DNode() {
        }

        public DNode(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }

    public LRUBaseHashTable() {
        this(DEFAULT_CAPACITY);
    }

    public LRUBaseHashTable(Integer capacity) {
        this.length = 0;
        this.capacity = capacity;

        headNode = new DNode<>();
        tailNode = new DNode<>();

        headNode.next = tailNode;
        tailNode.prev = headNode;

        table = new HashTable<>();
    }

    //将新节点添加到头部
    private void addNode(DNode<K, V> newNode) {
        newNode.next = headNode.next;
        newNode.prev = headNode;

        headNode.next.prev = newNode;
        headNode.next = newNode;
    }

    //移除节点
    private void removeNode(DNode<K, V> node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    //弹出尾部数据节点
    private DNode<K, V> popTail() {
        DNode<K, V> node = tailNode.prev;
        removeNode(node);
        return node;
    }

    //将节点移动到头部
    private void moveToHead(DNode<K, V> node) {
        removeNode(node);
        addNode(node);
    }

    //新增
    public void addNode(K key, V value) {
        DNode<K, V> node = table.get(key);

        if (node == null) {
            DNode<K, V> newNode = new DNode<>(key, value);
            table.put(key, newNode);
            addNode(newNode);

            if (++length > capacity) {
                DNode<K, V> tail = popTail();
                table.remove(tail.key);
                length--;
            }
        } else {
            node.value = value;
            moveToHead(node);
        }
    }

    //获取节点数据
    public V get(K key) {
        DNode<K, V> node = table.get(key);

        if (node == null) return null;

        moveToHead(node);
        return node.value;
    }

    //移除节点数据
    public void remove(K key) {
        DNode<K, V> node = table.get(key);

        if (node == null) return;

        removeNode(node);
        length--;
        table.remove(node.key);
    }

    public void printAll() {
        DNode<K, V> node = headNode.next;
        while (node.next != null) {
            System.out.print(node.value + ",");
            node = node.next;
        }
        System.out.println();
    }
}
